package com.gwcm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.gwcm.config.AlipayConfig;
import com.gwcm.exception.BusinessException;
import com.gwcm.factory.PaymentFactory;
import com.gwcm.handler.PaymentHandler;
import com.gwcm.mapper.MemberCardMapper;
import com.gwcm.mapper.OrderInfoMapper;
import com.gwcm.model.dto.alipay.AlipayPayNotify;
import com.gwcm.model.entity.CardOrderInfo;
import com.gwcm.model.entity.MemberCard;
import com.gwcm.model.enums.PaymentTypeEnum;
import com.gwcm.security.enums.AlipayNotifyTypeEnum;
import com.gwcm.service.CardOrderInfoService;
import com.gwcm.service.IPayService;
import com.gwcm.util.OrderNoUtils;
import com.yhz.commonutil.common.ErrorCode;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Optional;

/**
 * @author yanhuanzhan
 * @date 2023/3/3 - 16:55
 */
@Service
@Slf4j
public class PayServiceImpl implements IPayService {
    @Resource
    private CardOrderInfoService cardOrderInfoService;
    @Resource
    private MemberCardMapper memberCardMapper;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private PaymentFactory paymentFactory;
    @Resource
    private AlipayConfig alipayConfig;
    //@Resource
    //private RabbitTemplate rabbitTemplate;
    @Override
    public String preOrder(String orderNo) {
        CardOrderInfo cardOrderInfo = cardOrderInfoService.getByOrderNo(orderNo);
        if (cardOrderInfo == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        Long memberCardId = cardOrderInfo.getMemberCardId();
        MemberCard memberCard = Optional.ofNullable(memberCardMapper.selectById(memberCardId))
                .orElseThrow(()->new BusinessException(ErrorCode.NULL_ERROR));
        BigDecimal price = memberCard.getDiscountPrice();
        //元转分
        Integer newPrice = price.multiply(new BigDecimal(100)).intValue();

        PaymentHandler handler = paymentFactory.getHandler(PaymentTypeEnum.ALI_PAY);
        String formStr = handler.pcPreOrder(orderNo, memberCard.getCardName(), alipayConfig.getNotifyDomain()
                .concat(AlipayNotifyTypeEnum.PC_NOTIFY.getType()), newPrice);
        return formStr;
    }

    @Override
    public String aliPayAcceptNotify(Map<String, String> params) {
        String result;
        try {
            result = "failure";
            AlipayPayNotify payNotify = JSONObject.parseObject(JSONObject.toJSONString(params), AlipayPayNotify.class);
            log.info("paynotify params:{}", payNotify);
            //异步通知验签
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    alipayConfig.getAlipayPublicKey(),
                    AlipayConstants.CHARSET_UTF8,
                    AlipayConstants.SIGN_TYPE_RSA2);

            if (!signVerified) {
                //验签失败则记录异常日志，并在response中返回failure.
                log.error("支付结果异步通知验签失败！");
                return result;
            }
            // 验签成功后
            log.info("支付成功异步通知验签成功！");
            //按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，
            Boolean checkResult = cardOrderInfoService.checkAlipayPayNotify(payNotify);
            if (!checkResult) {
                result = "failure";
                return result;
            }
            //处理业务 修改订单状态 记录支付日志
            cardOrderInfoService.processAlipayPayNotify(payNotify);
        } catch (AlipayApiException e) {
            result = "failure";
            return result;
        }
        result = "success";
        return result;
    }
    @Override
    public void closeOrder(String orderNo) throws AlipayApiException {
        PaymentHandler handler = paymentFactory.getHandler(PaymentTypeEnum.ALI_PAY);
        //调用关单接口
        handler.closeOrder(orderNo);
    }

    @Override
    public String createOrder(Long cardId, Long userId, PaymentTypeEnum paymentTypeEnum) {
        //创建订单编号
        String orderNo = OrderNoUtils.getOrderNo();
        cardOrderInfoService.createOrder(cardId, userId, orderNo,paymentTypeEnum);
        return orderNo;
    }
}